////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Shader extension
//  Copyright (C), Crytek Studios, 2001-2004.
// -------------------------------------------------------------------------
//  File name:   VertexLib.cfi
//  Version:     v1.00
//  Created:     08/07/2006 by Tiago Sousa
//  Compilers:   
//  Description: Common vertex shader. Since almost all techniques share a similar
//  vertex shader, a common vertex shader has been created to save some work/code lines
//  and as an optimization at same time. 
//
//  Notes:
//    - When adding new features here, make sure it works with instancing
//
// -------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////

#if !%TEMP_VEGETATION

 #define INST_STREAM_CUSTOM                          \
  #if _RT_INSTANCING_ATTR || _RT_INSTANCING_CONST  \
    float4 InstAmbientOp  : TEXCOORDN;               \
   #if %_RT_FOG                                      \
    float4 InstAvgFogVolumeContrib   : TEXCOORDN;    \
   #endif                                            \
  #endif                                             \
  
#endif

///////////////// Vertex/texture modifiers //////////////////

#include "ModificatorVT.cfi"
#include "ModificatorTC.cfi"

///////////////// General vertex output //////////////////

struct v2f_sh
{
	#if _DS || _PS || !VS_TESSELLATION || _RT_NO_TESSELLATION
		float4 HPosition  : POSITION;
	#endif

	#if VS_TESSELLATION && !_RT_NO_TESSELLATION
		float4 vView     : TEXCOORDN;	// For shadow gen this is world position
		half4 vNormal    : TEXCOORDN;
	#endif

	#if (VS_TESSELLATION && !_RT_NO_TESSELLATION) || VS_ALPHATEST || VS_ALPHABLEND || VS_DRT4 || _RT_DISSOLVE
		float2 baseTC : TEXCOORDN;
	#endif	

	#if !_RT_HW_PCF_COMPARE || _RT_CUBEMAP0
		float Depth  : TEXCOORDN;
	#endif

	#if (!VS_TESSELLATION || _RT_NO_TESSELLATION) && VS_DRT4
		half3 Normal  : TEXCOORDN;
		float2 Depth2  : TEXCOORDN;
	#endif
};

struct vert2FragGeneral
{  
#if _DS || _PS || !VS_TESSELLATION || _RT_NO_TESSELLATION
  OUT_P
#endif  
  float4 baseTC     : TEXCOORDN;

#if %_RT_FOG || %ANISO_SPECULAR || %MULTILAYER || %TEMP_EYES || %OFFSETBUMPMAPPING || %PARALLAX_OCCLUSION_MAPPING
  float4 vTangent  : TEXCOORDN;
  float4 vBinormal : TEXCOORDN;
#endif

  float4 vView     : TEXCOORDN;       
  
#ifdef PS3 || XENON
  float4 screenProj : TEXCOORDN;   //z used for instanced alpha test value
#else
	float4 screenProj : TEXCOORDN_centroid;   //z used for instanced alpha test value
#endif

#if %_LT_LIGHTS && %_LT_HASPROJ  
  float4 projTC     : TEXCOORDN;
#endif    

#if %_RT_DECAL_TEXGEN_2D 
  float3 DistAtten : TEXCOORDN;
#endif  

#if %_RT_FOG && !%_RT_DECAL_TEXGEN_2D
  float4 AvgFogVolumeContrib : TEXCOORDN;
#endif

#if %_RT_FOG || %_RT_DECAL_TEXGEN_2D || %DECAL
  float4 Ambient   : TEXCOORDN;
#endif

#ifdef VS_TESSELLATION && !_RT_NO_TESSELLATION
  half4 vNormal    : TEXCOORDN;
#endif

#if %VERTCOLORS || %DIRTLAYER || %BLENDLAYER
	float4 Color      : COLOR0;
#endif

	MSAA_SAMPLE_INDEX_PS
};

struct geom2FragGeneral
{
	vert2FragGeneral IN;
};

struct vert2fragZ
{
 #if _DS || _PS || !VS_TESSELLATION || _RT_NO_TESSELLATION
  OUT_P
 #endif

 #if XENON && %_RT_SCATTERSHADE
	float4  ZInfo     : TEXCOORDN;
 #else
  #if !PS3 && !XENON
   float4 ZInfo     : TEXCOORDN_centroid;
  #endif
 #endif
 
	float4 baseTC     : TEXCOORDN;

	// for debugging edges
//#if %_RT_MSAA_QUALITY
//	float4 baseTC_centroid     : TEXCOORDN_centroid;
//#endif

	#if (!TEMP_TERRAIN || VS_ALPHABLEND) && !%GRASS
		half4 vTangent   : TEXCOORDN;
		#if _RT_DISSOLVE
			half4 vBinormal  : TEXCOORDN;  
		#else
			half3 vBinormal  : TEXCOORDN;  
		#endif
	#endif

	#if VS_TESSELLATION && !_RT_NO_TESSELLATION
		float4 vView     : TEXCOORDN;
		half4 vNormal    : TEXCOORDN;      
	#endif

	#if TEMP_TERRAIN || %GRASS
		#if %GRASS && _RT_DISSOLVE
			half4 vNormal   : TEXCOORDN;
		#else
			half3 vNormal   : TEXCOORDN;    
		#endif  
	#endif

	#if %OFFSETBUMPMAPPING || %PARALLAX_OCCLUSION_MAPPING
		float3 viewTS   : TEXCOORDN;
	#endif
	
  #if %BLENDLAYER
		float4 Color      : COLOR0;
	#endif

//#if _PS
//  #if %_RT_MSAA_QUALITY || %_RT_MSAA_QUALITY1
//    uint uSample  : SV_SAMPLEINDEX;
//  #endif
//#endif
};


///////////////// Shared vertex shader computations //////////////////

#if %SILHOUETTE_PARALLAX_OCCLUSION_MAPPING
void vs_shared_output( in app2vertGeneral IN, inout vert2FragGeneral OUT, inout vert2GeomGeneral OUT_ext, inout VSVertexContext vertPassPos, bool bUseBump )
#else
void vs_shared_output( in app2vertGeneral IN, inout vert2FragGeneral OUT, inout VSVertexContext vertPassPos, bool bUseBump )
#endif
{
  // Common data
  
  streamPos_FromGeneral(IN, vertPassPos);

#if %SILHOUETTE_PARALLAX_OCCLUSION_MAPPING
	const float3 SilPomDispl = SilPomDisplacement * TangNormal(IN.vertCommon.Tangent, IN.vertCommon.Binormal);
	vertPassPos.Position.xyz += SilPomDispl * -HeightBias;
#endif

  float4 vPosDecal = vertPassPos.Position;
  
  float4 HPosition = Pos_VS_General(g_VS_ViewProjZeroMatr, vertPassPos);     
  float3 vNorm = vertPassPos.ObjToTangentSpace[2];

  float4 baseTC = vertPassPos.baseTC;
#if %_RT_DECAL_TEXGEN_2D 
	_TCModifyDecal( vertPassPos, baseTC, OUT.DistAtten );
#endif

  // Apply texture modifiers
 _TCModify(baseTC, OUT.baseTC, vertPassPos.Position, vNorm, TS_DIFFUSE);
 
 if (bUseBump)
 {
   float4 bumpTC;
   _TCModify(baseTC, bumpTC, vertPassPos.Position, vNorm, TS_BUMP);
   OUT.baseTC.zw = bumpTC.xy;
 } 

#if %_RT_FOG || %_RT_DECAL_TEXGEN_2D || %DECAL

  // Output ambient color - for alpha blending, recursive rendering passes, decals also require ambient.w (opacity parameter)
   OUT.Ambient = AmbientOp;

  #if _RT_INSTANCING_ATTR || _RT_INSTANCING_CONST
    #fetchinst (OUT.Ambient = IN.InstAmbientOp, vertPassPos.nInstance);
  #endif

#endif

#if %_RT_FOG || %ANISO_SPECULAR || %MULTILAYER || %TEMP_EYES || %OFFSETBUMPMAPPING || %PARALLAX_OCCLUSION_MAPPING
    // Output tangents only for cases that require it - alpha blending, recursive passes and anisotropic specular
    // Note: Normalization required for normal diffuse map in world space in case scale used - Do not remove
    float3 worldTangentS = normalize( mul((const float3x3)vertPassPos.InstMatrix, vertPassPos.ObjToTangentSpace[0]) );
    float3 worldTangentT = normalize( mul((const float3x3)vertPassPos.InstMatrix, vertPassPos.ObjToTangentSpace[1]) );
    float3 worldTangentN = (cross(worldTangentS, worldTangentT)) * vertPassPos.Tangent.w;
    
    OUT.vTangent = float4(worldTangentS, vertPassPos.Tangent.w); 
    OUT.vBinormal.xyz = worldTangentT;
#endif

  OUT.vView.xyz = vertPassPos.WorldPos.xyz;
#if _RT_OBJ_IDENTITY
  OUT.vView.xyz -= g_VS_WorldViewPos.xyz;
#else
  vertPassPos.WorldPos.xyz += g_VS_WorldViewPos.xyz;
#endif
  
#if !VS_TESSELLATION || _RT_NO_TESSELLATION
  OUT.HPosition = HPosition;
#else
  OUT.vNormal.xyz = normalize(mul((const float3x3)vertPassPos.InstMatrix, vertPassPos.Normal.xyz));
#endif

  // Output the screen-space texture coordinates - for shadows and general projections
  OUT.screenProj = HPosToScreenTC(HPosition);

   // Output projection
#if %_LT_LIGHTS && %_LT_HASPROJ  
  OUT.projTC = mul(LightMatrix, vertPassPos.WorldPos);
#endif	 

  // Output fog into view-vector W component (to save interpolator)
#if %_RT_FOG && !%_RT_DECAL_TEXGEN_2D
  OUT.vView.w = GetVolumetricFogDensity(OUT.vView.xyz + g_VS_WorldViewPos.xyz);

 #if _RT_INSTANCING_ATTR || _RT_INSTANCING_CONST
   #fetchinst (OUT.AvgFogVolumeContrib = IN.InstAvgFogVolumeContrib, vertPassPos.nInstance);  
 #else
   OUT.AvgFogVolumeContrib = AvgFogVolumeContrib;
 #endif

 #if !VS_ALPHABLEND
    // additive blending case
    OUT.AvgFogVolumeContrib.w *= OUT.vView.w;
    OUT.AvgFogVolumeContrib.xyz = 0.0;
 #endif
#else
  OUT.vView.w = vertPassPos.Position.w;    
#endif

#if %VERTCOLORS || %DIRTLAYER || %BLENDLAYER
  OUT.Color = vertPassPos.Color;
#endif

}

/////////////////////// eof ///
